<?php

declare(strict_types=1);

namespace App\Service;

use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Library\Common;
use App\Model\Aftersale;
use App\Model\AftersaleProduct;
use App\Model\FlyGourmetMealConf;
use App\Model\FlyOrder;
use App\Model\FlyOrderProduct;
use App\Model\FlyShopDelivery;
use App\Model\ReservedSeatsSet;
use App\Model\ShopSendAddress;
use Hyperf\Database\Model\Builder;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

/**
 * 商家订单服务
 * Class ShopOrderService
 * @package App\Service
 */
class ShopOrderService extends BaseService
{


    /**
     * @Inject
     * @var DeliverySendService
     */
    private $sendDelivery;

    /**
     * @Inject
     * @var PayService
     */
    private $pay;

    /**
     * @Inject
     * @var ShopDeliveryConfigService
     */
    private $deliveryConfig;

    /**
     * @Inject
     * @var ShopSendAddressService
     */
    private $sendAddr;

    /**
     * @Inject
     * @var AftersaleSetService
     */
    private $orderSet;

    /**
     * @Inject
     * @var FlyOrderService
     */
    private $order;

    /**
     * @Inject
     * @var AftersaleService
     */
    private $aftersale;

    // 筛选参数
    const TYPE_WAIT_CHECK = 1;// 待处理
    const TYPE_ORDER = 2; // 订单
    const TYPE_AFTERSALE = 3; // 售后单
    // 订单筛选参数
    const STATUS_WAIT_PAY = 1; // 待付款
    const STATUS_WAIT_DELIVERY = 2; // 待发货
    const STATUS_WAIT_LOCAL_SEND = 3; // 待配送
    const STATUS_WAIT_OWN_RECEIVE = 4; // 待自提
    const STATUS_WAIT_RECEIVE = 5; // 待签收
    const STATUS_FINISHED = 6; // 已完成
    const STATUS_CANCELED = 7; // 已取消
    const STATUS_WAIT_USE = 8; //待使用

    // 待处理筛选参数
    const WAIT_SEND = 1; // 待发货
    const WAIT_REFUND = 2; // 待退款
    const WAIT_SWAP = 3; // 待换货
    const WAIT_REPAIR = 4; // 待维修
    const WAIT_DELIVERY = 5; // 待配送
    const WAIT_OWN_RECEIVE = 6; // 待自提
    const WAIT_USE = 7; // 待使用

    // 售后筛选参数
    const AF_WAIT_CHECK = 1; //售后待审核
    const AF_FINISHED = 2; // 售后已完成
    const AF_REFUSED = 3; // 售后被驳回
    // 状态值
    const WAIT_CHECK_STATUS = 0;// 待处理状态值

    /**
     * 获取商家端列表
     * @param int $shop_id
     * @param int $type
     * @param int $status
     * @param string $keyword
     * @return Builder
     */
    public function getList(int $shop_id, $type = 1, int $status = 1, $keyword = ''): Builder
    {

        echo $type . "---------" . $status;
        $wheres = function ($where) use ($type, $status) {
            // 筛选类型 (需要统计数量)
            $field = "";
            $value = 0;
            switch ($type) {
                case self::TYPE_ORDER: // 订单筛选
                    // 筛选状态
                    switch ($status) {
                        case self::STATUS_WAIT_PAY://待付款
                            $field = "fly_order.order_status";
                            $value = FlyOrderService::STATUS_WAIT_PAY;
                            break;
                        case self::STATUS_WAIT_DELIVERY:// 待发货
                            $value = 0;
                            $where->whereIn('delivery_type', [ShopDeliveryConfigService::TYPE_EXPRESS, ShopDeliveryConfigService::TYPE_VIRTUAL])
                                ->where("fly_order.delivery_id", '=', 0)
                                ->where('order_status', '=', FlyOrderService::STATUS_WAIT_RECEIVE)
                                ->where('order_style', '=', 1)
                                ->where('is_pay', '=', 1);// 已支付待发货
                            break;
                        case self::STATUS_WAIT_LOCAL_SEND:// 待配送
                            $value = 0;
                            $where->where('delivery_type', '=', ShopDeliveryConfigService::TYPE_LOCAL)
                                ->where('order_status', '=', FlyOrderService::STATUS_WAIT_RECEIVE)
                                ->where("fly_order.delivery_id", '=', 0)
                                ->where('is_pay', '=', 1);// 已支付待配送
                            break;
                        case self::STATUS_WAIT_OWN_RECEIVE:// 待自提
                            $value = 0;
                            $where->where('delivery_type', '=', ShopDeliveryConfigService::TYPE_OWN)
                                ->where('order_status', '=', FlyOrderService::STATUS_WAIT_RECEIVE)
                                ->where("fly_order.is_received", '=', 0)
                                ->where('is_pay', '=', 1);
                            break;
                        case self::STATUS_WAIT_RECEIVE:// 代签收
                            $value = 0;
                            $where->whereIn('fly_order.delivery_type', [ShopDeliveryConfigService::TYPE_LOCAL, ShopDeliveryConfigService::TYPE_EXPRESS])
                                ->where('fly_order.is_received', '=', 0)
                                ->where('fly_order.delivery_id', '>', 0);// 已发货 或 已配送
                            break;
                        case self::STATUS_FINISHED:// 已完成
                            $field = "fly_order.order_status";
                            $value = FlyOrderService::STATUS_FINISHED;
                            break;
                        case self::STATUS_CANCELED:// 已取消
                            $field = "fly_order.order_status";
                            $value = FlyOrderService::STATUS_CLOSED;
                            break;
                        case self::STATUS_WAIT_USE:// 待使用
                            $value = 0;
                            // 订座点餐
                            $where->whereIn('order_style', [2, 3])
                                ->where('is_pay', '=', 1)
                                ->where('order_status', '=', FlyOrderService::STATUS_WAIT_RECEIVE);
                            break;
                    }
                    break;
                case self::TYPE_WAIT_CHECK: // 待处理筛选
                    switch ($status) {
                        case self::WAIT_SEND: // 待发货
                            $value = 0;
                            $where->whereIn('delivery_type', [ShopDeliveryConfigService::TYPE_EXPRESS, ShopDeliveryConfigService::TYPE_VIRTUAL])
                                ->where('order_status', '=', FlyOrderService::STATUS_WAIT_RECEIVE)
                                ->where("fly_order.delivery_id", '=', 0)
                                ->where('order_style', '=', 1)
                                ->where('is_pay', '=', 1);
                            break;
                        case self::WAIT_DELIVERY:// 待配送
                            $value = 0;
                            $where->where('delivery_type', '=', ShopDeliveryConfigService::TYPE_LOCAL)
                                ->where('order_status', '=', FlyOrderService::STATUS_WAIT_RECEIVE)
                                ->where('fly_order.delivery_id', '=', 0)
                                ->where('is_pay', '=', 1);
                            break;
                        case self::WAIT_OWN_RECEIVE: // 待自提
                            $value = 0;
                            $where->where('delivery_type', '=', ShopDeliveryConfigService::TYPE_OWN)
                                ->where('order_status', '=', FlyOrderService::STATUS_WAIT_RECEIVE)
                                ->where('fly_order.is_received', '=', 0)
                                ->where('is_pay', '=', 1);
                            break;
                        case self::WAIT_USE: // 待使用
                            $value = 0;
                            // 订座点餐
                            $where->whereIn('order_style', [2, 3])
                                ->where('is_pay', '=', 1)
                                ->where('order_status', '=', FlyOrderService::STATUS_WAIT_RECEIVE);
                            break;
                        case self::WAIT_REFUND: // 待退款
                            $value = ""; // 未退款
                            $where->whereIn('af_status', [AftersaleService::STATUS_CHECKED, AftersaleService::STATUS_WAIT_CHECK])
                                ->whereIn('af_type', [AftersaleService::TYPE_REFUND, AftersaleService::TYPE_REFUND_P]);// 退货、退款类型
                            break;
                        case self::WAIT_SWAP: // 待换货
                            $field = "fly_aftersale.af_type";
                            $value = AftersaleService::TYPE_SWAP;
                            $where->whereIn('af_status', [AftersaleService::STATUS_CHECKED, AftersaleService::STATUS_WAIT_CHECK]);
                            break;
                        case self::WAIT_REPAIR: // 待维修
                            $field = "fly_aftersale.af_type";
                            $value = AftersaleService::TYPE_REPAIR;
                            $where->whereIn('af_status', [AftersaleService::STATUS_CHECKED, AftersaleService::STATUS_WAIT_CHECK]);
                            break;
                    }
                    break;
                case self::TYPE_AFTERSALE: // 售后单
                    $field = "fly_aftersale.af_status";
                    switch ($status) {
                        case self::AF_WAIT_CHECK: // 待审核
                            $value = ""; // 待审核+待完成
                            $where->whereIn('af_status', [AftersaleService::STATUS_CHECKED, AftersaleService::STATUS_WAIT_CHECK]);
                            break;
                        case self::AF_FINISHED: // 已完成
                            $value = "";
                            $where->whereIn('fly_aftersale.af_status', [AftersaleService::STATUS_CANCEL, AftersaleService::STATUS_FINISHED]);
                            break;
                        case self::AF_REFUSED: // 被驳回
                            $value = AftersaleService::STATUS_REFUSED;
                            break;
                    }
                    break;
            }
            if (!empty($value)) {
                $where->where([$field => $value]);
            }
        };

        if (self::TYPE_ORDER == $type || (self::TYPE_WAIT_CHECK == $type && in_array($status, [self::WAIT_SEND, self::WAIT_OWN_RECEIVE, self::WAIT_DELIVERY, self::STATUS_WAIT_USE]))) {
            // 订单
            $instance = make(FlyOrder::class)
                ->with(['with_address_info', 'with_current_af', 'with_delivery', 'with_delivery_log'])
                ->where($wheres)
                ->where(function ($where) use ($keyword) {
                    if (!empty($keyword)) {
                        $where->where('order_sn', 'like', '%' . $keyword . '%');
                    }
                })
                ->orderBy('fly_order.order_status', 'asc')// 待付款-待收货-已完成-已关闭
                ->orderBy('fly_order.create_time', 'desc');
        } elseif (self::TYPE_AFTERSALE == $type) {
            // 售后
            $instance = make(Aftersale::class)
                ->where(function ($where) use ($keyword) {
                    if (!empty($keyword)) {
                        $where->where('af_sn', 'like', '%' . $keyword . '%');
                    }
                })
                ->with(['with_user_address', 'with_order', 'with_shop_address', 'with_shop_change_address'])
                ->where($wheres);
            if (in_array($status, [self::AF_FINISHED, self::AF_REFUSED])) {
                // 已完成已关闭排序规则：审核时间降序排序，新审核的在最上面
                $instance->orderBy('check_time', 'desc');
            } else {
                // 待审核排序规则： 按申请时间降序排序
                $instance->orderBy('apply_time', 'desc');
            }
        } else {
            // 混合展示:待发货
            if (in_array($status, [self::WAIT_SEND, self::WAIT_OWN_RECEIVE, self::WAIT_DELIVERY, self::WAIT_USE])) {
                $instance = make(FlyOrder::class)
                    ->with(['with_address_info', 'with_current_af', 'with_delivery', 'with_delivery_log'])
                    ->where(function ($where) use ($keyword) {
                        if (!empty($keyword)) {
                            $where->where('order_sn', 'like', '%' . $keyword . '%');
                        }
                    })
                    ->where($wheres)
                    ->orderBy('fly_order.order_status', 'asc')// 待付款-待收货-已完成-已关闭
                    ->orderBy('fly_order.create_time', 'desc');
            } else {
                $instance = make(Aftersale::class)
                    ->with(['with_user_address', 'with_order', 'with_order', 'with_shop_address', 'with_shop_change_address'])
                    ->where(function ($where) use ($keyword) {
                        if (!empty($keyword)) {
                            $where->where('af_sn', 'like', '%' . $keyword . '%');
                        }
                    })
                    ->where($wheres)
                    ->orderByRaw("field(af_status,1,2) asc") // 按 待审核、已审核排序
                    ->orderByRaw("field(af_type,1,2,3,4) asc") // 按 待退款、退货退款、换货、维修 排序
                    ->orderByRaw("user_response_time desc"); // 按 最新回传单号用户排序
            }
        }
        return $instance->with(['with_products'])->where(['shop_id' => $shop_id]);
    }

    /**
     * @param int $shop_id
     * @param int|null $tag
     * @return array
     */
    public function getSearchTag(int $shop_id, int $tag = self::TYPE_WAIT_CHECK): array
    {
        // 先统计选项数量
        $return = [];
        // 待发货 待配送 待自提 待退款 待换货 待维修
        // 待处理 已完成(用户撤销的售后) 被驳回
        // 待付款 待发货 待配送 待自提 代签收 已完成 已取消
        $delivery_config = $this->deliveryConfig->getDeliveryConfigs($shop_id, 1);// 启用的配置
        $configs = array_column($delivery_config, 'delivery_type');
        $configs[] = 4;// 兼容虚拟产品

        // 店铺入驻状态
        $meal_show = make(FlyGourmetMealConf::class)->where('shop_id', '=', $shop_id)->exists();
        $seat_show = make(ReservedSeatsSet::class)->where('shop_id', '=', $shop_id)->exists();


        switch ($tag) {
            case self::TYPE_ORDER:// 订单
                $return = [
                    [
                        'tag_status' => self::STATUS_WAIT_PAY,
                        'tag_name' => '待付款',
                        'is_show' => 1,
                        'count' => $this->order->getModelInstance()->where(['shop_id' => $shop_id, 'order_status' => 1])->count()
                    ],
                    [
                        'tag_status' => self::STATUS_WAIT_DELIVERY, // 待发货
                        'tag_name' => '待发货',
                        'is_show' => in_array(ShopDeliveryConfigService::TYPE_EXPRESS, $configs) ? 1 : 0,
                        'count' => $this->order->getModelInstance()
                            ->where([
                                'shop_id' => $shop_id,
                                'order_status' => FlyOrderService::STATUS_WAIT_RECEIVE,
                                'order_style' => FlyOrderService::STYLE_SHOP,
                                'delivery_id' => 0])
                            ->whereIn('delivery_type', [ShopDeliveryConfigService::TYPE_EXPRESS, ShopDeliveryConfigService::TYPE_VIRTUAL])
                            ->count()
                    ],
                    [
                        'tag_status' => self::STATUS_WAIT_LOCAL_SEND, // 待配送
                        'tag_name' => '待配送',
                        'is_show' => in_array(ShopDeliveryConfigService::TYPE_EXPRESS, $configs) ? 1 : 0,
                        'count' => $this->order->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'delivery_type' => ShopDeliveryConfigService::TYPE_LOCAL,
                            'order_status' => FlyOrderService::STATUS_WAIT_RECEIVE,
                            'delivery_id' => 0])->count()
                    ],
                    [
                        'tag_status' => self::STATUS_WAIT_OWN_RECEIVE, // 待自提
                        'tag_name' => '待自提',
                        'is_show' => in_array(ShopDeliveryConfigService::TYPE_OWN, $configs) ? 1 : 0,
                        'count' => $this->order->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'delivery_type' => ShopDeliveryConfigService::TYPE_OWN,
                            'order_status' => FlyOrderService::STATUS_WAIT_RECEIVE
                        ])->count()
                    ],
                    [
                        'tag_status' => self::STATUS_WAIT_RECEIVE,
                        'tag_name' => '代签收',
                        'is_show' => 1,
                        'count' => $this->order->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'order_status' => FlyOrderService::STATUS_WAIT_RECEIVE
                        ])->where('delivery_id', '>', 0)->count()
                    ],
                    [
                        'tag_status' => self::STATUS_WAIT_USE,
                        'tag_name' => '待使用',
                        'is_show' => ($meal_show || $seat_show) ? 1 : 0,
                        'count' => $this->order->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'order_status' => FlyOrderService::STATUS_WAIT_RECEIVE
                        ])->whereIn('order_style', [2, 3])->count()
                    ],
                    [
                        'tag_status' => self::STATUS_FINISHED,
                        'tag_name' => '完成',
                        'is_show' => 1,
                        'count' => $this->order->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'order_status' => FlyOrderService::STATUS_FINISHED
                        ])->count()
                    ],
                    [
                        'tag_status' => self::STATUS_CANCELED,
                        'tag_name' => '已取消',
                        'is_show' => 1,
                        'count' => $this->order->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'order_status' => FlyOrderService::STATUS_CLOSED
                        ])->count()
                    ]
                ];
                $return[1]['is_show'] = $return[1]['count'] > 0 ? 1 : $return[1]['is_show'];
                $return[2]['is_show'] = $return[2]['count'] > 0 ? 1 : $return[2]['is_show'];
                $return[3]['is_show'] = $return[3]['count'] > 0 ? 1 : $return[3]['is_show'];
                break;
            case self::TYPE_WAIT_CHECK:// 待处理
                $return = [
                    [
                        'tag_status' => self::WAIT_SEND, // 待发货
                        'tag_name' => '待发货',
                        'is_show' => in_array(ShopDeliveryConfigService::TYPE_EXPRESS, $configs) ? 1 : 0,
                        'count' => $this->order->getModelInstance()
                            ->where([
                                'shop_id' => $shop_id,
                                'delivery_id' => 0,
                                'order_style' => FlyOrderService::STYLE_SHOP,
                                'order_status' => FlyOrderService::STATUS_WAIT_RECEIVE
                            ])
                            ->whereIn('delivery_type', [ShopDeliveryConfigService::TYPE_EXPRESS, ShopDeliveryConfigService::TYPE_VIRTUAL])
                            ->count()
                    ], [
                        'tag_status' => self::WAIT_DELIVERY,// 待配送
                        'tag_name' => '待配送',
                        'is_show' => in_array(ShopDeliveryConfigService::TYPE_EXPRESS, $configs) ? 1 : 0,
                        'count' => $this->order->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'delivery_type' => ShopDeliveryConfigService::TYPE_LOCAL,
                            'order_status' => FlyOrderService::STATUS_WAIT_RECEIVE,
                            'delivery_id' => 0])->count()
                    ], [
                        'tag_status' => self::WAIT_OWN_RECEIVE, // 待自提
                        'tag_name' => '待自提',
                        'is_show' => in_array(ShopDeliveryConfigService::TYPE_OWN, $configs) ? 1 : 0,
                        'count' => $this->order->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'delivery_type' => ShopDeliveryConfigService::TYPE_OWN,
                            'order_status' => FlyOrderService::STATUS_WAIT_RECEIVE
                        ])->count()
                    ], [
                        'tag_status' => self::WAIT_USE,
                        'tag_name' => '待使用',
                        'is_show' => ($meal_show || $seat_show) ? 1 : 0,
                        'count' => $this->order->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'order_status' => FlyOrderService::STATUS_WAIT_RECEIVE
                        ])->whereIn('order_style', [2, 3])->count()
                    ], [
                        'tag_status' => self::WAIT_REFUND, // 待退款
                        'tag_name' => '待退款',
                        'is_show' => 1,
                        'count' => $this->aftersale->getModelInstance()->where(['shop_id' => $shop_id])
                            ->whereIn('af_status', [AftersaleService::STATUS_CHECKED, AftersaleService::STATUS_WAIT_CHECK])
                            ->whereIn('af_type', [AftersaleService::TYPE_REFUND, AftersaleService::TYPE_REFUND_P])
                            ->count()
                    ], [
                        'tag_status' => self::WAIT_SWAP, // 待换货
                        'tag_name' => '待换货',
                        'is_show' => 1,
                        'count' => $this->aftersale->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'af_type' => AftersaleService::TYPE_SWAP
                        ])->whereIn('af_status', [AftersaleService::STATUS_CHECKED, AftersaleService::STATUS_WAIT_CHECK])
                            ->count()
                    ], [
                        'tag_status' => self::WAIT_REPAIR, // 待维修
                        'tag_name' => '待维修',
                        'is_show' => 1,
                        'count' => $this->aftersale->getModelInstance()->where([
                            'shop_id' => $shop_id,
                            'af_type' => AftersaleService::TYPE_REPAIR
                        ])->whereIn('af_status', [AftersaleService::STATUS_CHECKED, AftersaleService::STATUS_WAIT_CHECK])
                            ->count()
                    ]
                ];
                $return[0]['is_show'] = $return[0]['count'] > 0 ? 1 : $return[0]['is_show'];
                $return[1]['is_show'] = $return[1]['count'] > 0 ? 1 : $return[1]['is_show'];
                $return[2]['is_show'] = $return[2]['count'] > 0 ? 1 : $return[2]['is_show'];
                break;
            case self::TYPE_AFTERSALE:// 售后
                $af_count = $this->aftersale->getModelInstance()
                    ->where(['shop_id' => $shop_id])
                    ->selectRaw("count(case when af_status = 1 then 1 end) as wait_check_num,
                    count(case when af_status = 2 then 1 end) as checked_num,
                    count(case when af_status = 3 then 1 end) as finish_num,
                    count(case when af_status = 4 then 1 end) as refuse_num,
                    count(case when af_status = 5 then 1 end) as close_num")
                    ->first();
                $af_count = empty($af_count) ? [] : $af_count->toArray();
                $return = [
                    [
                        'tag_status' => self::AF_WAIT_CHECK,
                        'tag_name' => '待处理',
                        'is_show' => 1,
                        'count' => $af_count['wait_check_num'] + $af_count['checked_num']
                    ],
                    [
                        'tag_status' => self::AF_FINISHED,
                        'tag_name' => '完成',
                        'is_show' => 1,
                        'count' => $af_count['finish_num'] + $af_count['close_num']
                    ],
                    [
                        'tag_status' => self::AF_REFUSED,
                        'tag_name' => '驳回',
                        'is_show' => 1,
                        'count' => $af_count['refuse_num']
                    ]
                ];
                break;
        }
        return $return;
    }

    /**
     * 获取订单详情
     * @param int $order_id
     * @param int $shop_id
     * @return array
     */
    public function getOrderDetails(int $order_id, int $shop_id): array
    {
        $list = $this->order->getInstance()->where(['shop_id' => $shop_id, 'order_id' => $order_id])
            ->with(['with_products', 'with_delivery_log', 'with_address_info', 'with_current_af'])
            ->first();
        if (empty($list)) {
            return [];
        }
        $datum = $list->toArray();
        if (isset($datum['with_delivery_log']['with_log']) && $datum['with_delivery_log']['with_log'] != '') {
            $datum['with_delivery_log']['with_log'][] = [
                "time" => $datum['with_delivery_log']['created_at'],
                "status_code" => -1,
                "status" => "发货",
            ];
            $datum['with_delivery_log']['with_log'][] = [
                "time" => date('Y-m-d H:i:s', $datum['paid_time']),
                "status_code" => -2,
                "status" => "下单",
            ];
        }
        $order_set = $this->orderSet->getTimeSet(AftersaleSetService::TYPE_DO);
        $datum['is_outer'] = 0;
        $datum['outer_time'] = 0;
        $datum['outer_time_str'] = "";
        // 已支付-未发货
        if (!empty($order_set) && $datum['is_pay'] == 1 &&
            in_array($datum['delivery_type'], [ShopDeliveryConfigService::TYPE_EXPRESS, ShopDeliveryConfigService::TYPE_LOCAL])
            && empty($datum['delivery_id'])) {
            // 判断是否超时
            if ($datum['delivery_type'] == ShopDeliveryConfigService::TYPE_LOCAL) {
                if ($datum['date_time'] < time()) {
                    // 超时时长
                    $datum['outer_time'] = time() - $datum['date_time'];
                    $datum['is_outer'] = 1;
                } else {
                    // 剩余配送时长
                    $datum['outer_time'] = $datum['date_time'] - time();
                }
                $outer_time_arr = Common::formatSecondDuration($datum['outer_time']);
                $datum['outer_time_str'] = $outer_time_arr['day'] . "天" . $outer_time_arr['hour'] . "小时" . $outer_time_arr['min'] . "分";
                if ($datum['is_outer'] == 1) {
                    $datum['outer_time_str'] = "请及时配送，超时" . $datum['outer_time_str'];
                } else {
                    $datum['outer_time_str'] = "需求在" . date("Y-m-d H:i", $datum['date_time']) . "之前送达";
                }
            } else {
                $outer_time = time() - ($datum['pay_time'] + (86400 * $order_set['days']));
                if ($order_set['days'] != -1) {
                    $datum['outer_time'] = $outer_time;
                    // 已超时
                    if ($outer_time > 0) {
                        // 已超时
                        $datum['is_outer'] = 1;
                        $outer_time_arr = Common::formatSecondDuration($datum['outer_time']);
                    } else {
                        // 请在**时间内发货
                        $outer_time_arr = Common::formatSecondDuration(abs($datum['outer_time']));
                    }
                    $datum['outer_time_str'] = $outer_time_arr['day'] . "天" . $outer_time_arr['hour'] . "小时" . $outer_time_arr['min'] . "分";
                    if ($datum['is_outer'] == 1) {
                        $datum['outer_time_str'] = "请发货，超时" . $datum['outer_time_str'];
                    } else {
                        $datum['outer_time_str'] = "请在" . $datum['outer_time_str'] . "内发货";
                    }
                }
            }
        }
        return $datum;
    }

    /**
     * 售后单详情
     * @param int $shop_id
     * @param $af_sn
     * @return array
     */
    public function afDetails(int $shop_id, $af_sn): array
    {
        $af = $this->aftersale->getInstance()
            ->with(['with_products', 'with_order', 'with_user_address', 'with_shop_address', 'with_shop_change_address'])
            ->where(['af_sn' => $af_sn, 'shop_id' => $shop_id])
            ->first();
        return empty($af) ? [] : $af->toArray();
    }

    /**
     * 用户自提
     * @param int $shop_id
     * @param string $order_sn
     * @param int $charge_type
     * @param int|null $charge_code
     * @return bool
     */
    public function receiveBySelf(int $shop_id, string $order_sn, int $charge_type, ?int $charge_code): bool
    {
        $order_instance = $this->order->getInstance()
            ->where('order_sn', '=', $order_sn)
            ->where('shop_id', '=', $shop_id)
            ->first();
        if (empty($order_instance) || $order_instance->delete_time > 0) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '订单不存在');
        }
        // 非自提 - 非待收货
        if ($order_instance->delivery_type != ShopDeliveryConfigService::TYPE_OWN || $order_instance->order_status != FlyOrderService::STATUS_WAIT_RECEIVE) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '订单状态错误');
        }
        // 自提类型错误
        if (!in_array($charge_type, [FlyOrderService::CHARGE_TYPE_SCAN, FlyOrderService::CHARGE_TYPE_CODE])) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '参数错误');
        }
        $order_instance->charge_type = $charge_type;
        // 提货码提货
        if ($charge_type == FlyOrderService::CHARGE_TYPE_CODE) {
            if (empty($charge_code)) {
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '缺少参数');
            }
            $order_instance->charge_off_code = $charge_code;
        }
        $order_instance->order_status = FlyOrderService::STATUS_FINISHED;
        $order_instance->is_received = 1;
        $order_instance->received_time = time();
        return $order_instance->save();
    }

    /**
     * 虚拟产品发货
     * @param int $shop_id
     * @param string $order_sn
     * @return bool
     */
    public function virtualSend(int $shop_id, string $order_sn): bool
    {
        $order_instance = $this->order->getInstance()
            ->where('order_sn', '=', $order_sn)
            ->where('shop_id', '=', $shop_id)
            ->first();
        if (empty($order_instance) || $order_instance->delete_time > 0 || $order_instance->order_status != FlyOrderService::STATUS_WAIT_RECEIVE) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '订单不存在');
        }
        if ($order_instance->is_virtual != 1) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '非虚拟产品');
        }
        $order_instance->order_status = FlyOrderService::STATUS_FINISHED;
        $order_instance->is_received = 1;
        $order_instance->received_time = time();
        return $order_instance->save();
    }


    /**
     * 售后单审核(驳回、审核、修改商家收货地址、退款（自提配送审核通过即退款）)
     * @param int $shop_id
     * @param string $af_sn
     * @param int $act 1通过 2驳回
     * @param int $addr_id
     * @param int $is_back_delivery
     * @param int $is_back_coupon
     * @param string|null $af_refuse_reason
     * @return bool
     */
    public function aftersaleCheck(int $shop_id, string $af_sn, int $act, int $addr_id, int $is_back_delivery, int $is_back_coupon, ?string $af_refuse_reason): bool
    {
        $is_back_coupon = 1;
        $af_instance = make(Aftersale::class)
            ->where('shop_id', '=', $shop_id)
            ->where('af_sn', '=', $af_sn)
            ->first();
        if (empty($af_instance) || $af_instance->af_status != AftersaleService::STATUS_WAIT_CHECK) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '售后单状态错误');
        }
        // 是否修改
        if (!empty($addr_id)) {
            if (empty($this->sendAddr->getAddrById($shop_id, $addr_id))) {
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '地址错误');
            }
            // 修改地址
            if ($af_instance->shop_change_address_id != $addr_id && $af_instance->shop_change_address_id != $af_instance->shop_address_id) {
                // 替换更改过的地址
                if (!empty($af_instance->shop_change_address_id)) {
                    $af_instance->shop_address = $af_instance->shop_change_address_id;
                }
                $af_instance->shop_change_address_id = $addr_id;
            }
        }

        if ($act == 2) {
            // 审核驳回
            if (empty($af_refuse_reason)) {
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '未填写驳回原因');
            }
            $af_instance->refuse_reason = $af_refuse_reason;
            // 驳回原因
            $af_instance->af_status = AftersaleService::STATUS_REFUSED;

            // 释放售后占用商品
            $af_p_num = make(AftersaleProduct::class)->where([
                'af_id' => $af_instance->af_id
            ])->pluck('quantity', 'order_p_id');

            foreach ($af_p_num as $id => $quantity) {
                make(FlyOrderProduct::class)->where([
                    'id' => $id
                ])->whereRaw('free_num<=' . $quantity)
                    ->update(['free_num' => Db::raw('free_num+' . $quantity)]);
            }
            $af_instance->finish_time = time();
            return $af_instance->save();
        } else {
            // 审核通过（退货退款审核可以修改优惠券运费的退与不退）
            if ($af_instance->af_type == AftersaleService::TYPE_REFUND_P) {
                $refund_price = Common::yuan2fen(floatval($af_instance->should_refund_price));
                // 返还运费
                if ($is_back_delivery == 1 && $af_instance->is_back_delivery == 0) {
                    $refund_price += Common::yuan2fen(floatval($af_instance->can_back_delivery_price));
                    $af_instance->is_back_delivery = 1;
                    $af_instance->back_delivery_price = $af_instance->can_back_delivery_price;
                }
                // 不扣优惠
                if ($is_back_coupon == 1 && $af_instance->is_back_coupon == 0) {
                    $refund_price += Common::yuan2fen(floatval($af_instance->can_back_coupon_price));
                    $af_instance->is_back_delivery = 1;
                    $af_instance->back_delivery_price = $af_instance->can_back_delivery_price;
                }
                $af_instance->should_refund_price = Common::fen2yuan($refund_price);
            }
            // 申请通过
            $af_instance->af_status = AftersaleService::STATUS_CHECKED;
            $af_instance->check_time = time();
            if (!$af_instance->save()) {
                return false;
            }
            // 非物流方式发货：审核即退款（或直接退款）
            if (in_array($af_instance->af_type, [AftersaleService::TYPE_REFUND, AftersaleService::TYPE_REFUND_P])) {
                $order = $this->order->getDetails($af_instance->user_id, $af_instance->order_id);
                if ($order['delivery_type'] != ShopDeliveryConfigService::TYPE_EXPRESS) {
                    if (!$this->afRefund($shop_id, $af_sn, $af_instance->is_back_coupon, $af_instance->is_back_delivery)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     * 商家退款操作
     * @param int $shop_id
     * @param string $af_sn
     * @param int $back_coupon
     * @param int $back_delivery
     * @return bool
     */
    public function afRefund(int $shop_id, string $af_sn, int $back_coupon, int $back_delivery): bool
    {
        // 优惠券必须退
        $back_coupon = 1;
        Db::beginTransaction();
        try {
            $af_instance = $this->aftersale->getInstance()
                ->with(['with_products'])
                ->where(['shop_id' => $shop_id, 'af_sn' => $af_sn])
                ->whereIn('af_status', [AftersaleService::STATUS_WAIT_CHECK, AftersaleService::STATUS_CHECKED])
                ->whereIn('af_type', [1, 2])
                ->first();
            if (empty($af_instance)) {
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '售后单不存在');
            }
            $order_details = $this->order->getDetails($af_instance->user_id, $af_instance->order_id);
            // 退货退款 快递发货类型 需要先回传单号
            if ($af_instance->af_type == 2 && $order_details['delivery_type'] == 1 && empty($af_instance->user_response_sn)) {
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '退货退款需回传单号');
            }
            // （退还运费:加钱  不扣优惠：减钱） 0
            // 改为退换运费：加钱
            $refund_price = Common::yuan2fen(floatval($af_instance->should_refund_price));
            $af_arr = $af_instance->toArray();
            // 退货退款不可再次修改（todo：因为已修改过用户退还优惠券运费状态，为选中时不可再次修改
            if ($af_instance->af_type == AftersaleService::TYPE_REFUND_P) {
                goto refund;
            }

            // 整单退(不退优惠券不退运费)最高不超过订单金额
            if ($af_arr['is_all_back'] == 1) {
                if ($refund_price > Common::yuan2fen(floatval($order_details['paid_price']))) {
                    throw new BusinessException(ErrorCode::NORMAL_ERROR, '整单退，最高不超过订单支付金额:' . $order_details['paid_price']);
                } else {
                    // 原来不扣，商家不可改为扣
                    if ($af_instance->is_back_delivery == 1 && $back_delivery == 0) {
                        throw new BusinessException(ErrorCode::NORMAL_ERROR, '整单退：未发货或商家责任，不可扣除运费金额');
                    } elseif ($af_instance->is_back_delivery == 0 && $back_delivery == 1) {
                        // 不扣除运费
                        $refund_price += Common::yuan2fen(floatval($af_instance->back_delivery_price));
                    }
                }
            } else {
                // 部分退
                if ($af_instance->is_back_delivery == 0 && $back_delivery == 1) {
                    $refund_price += Common::yuan2fen(floatval($af_instance->back_delivery_price));
                } elseif ($af_instance->is_back_delivery == 1 && $back_delivery == 0) {
                    throw new BusinessException(ErrorCode::NORMAL_ERROR, '商家责任或未发货，需返还用户运费金额');
                }
                // 改为扣除优惠：加钱
                if ($af_instance->is_back_coupon == 0 && $back_coupon == 1) {
                    $refund_price += Common::yuan2fen(floatval($af_instance->back_coupon_price));
                } elseif ($af_instance->is_back_coupon == 1 && $back_coupon == 0) {
                    throw new BusinessException(ErrorCode::NORMAL_ERROR, '用户优惠券仍适用，不可扣除用户优惠金额');
                }
            }

            refund:
            $refund_price = Common::fen2yuan($refund_price);
            // 退款金额最小不得低于按规则计算金额
            if ($refund_price < $af_arr['should_refund_price']) {
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '退款金额最低不得少于售后规则计费金额(' . $af_arr['should_refund_price'] . ")");
            }

            /** ----------保存信息----------- **/
            $af_data = [
                'af_status' => AftersaleService::STATUS_FINISHED,
                'finish_time' => time(),
                'refund_price' => $refund_price,
                'is_refund' => 1,
                'refund_time' => time()
            ];
            // 仅退款时修改退款参数
            if ($af_instance->af_type == AftersaleService::TYPE_REFUND) {
                if (1 == $back_delivery && $af_instance->is_back_delivery == 0) {
                    $af_data['is_back_delivery'] = 1;
                    $af_data['back_delivery_price'] = Db::raw("can_back_delivery_price");
                }
                if (1 == $back_coupon && $af_instance->is_back_coupon == 0) {
                    $af_instance['is_back_coupon'] = 1;
                    $af_data['back_coupon_price'] = Db::raw('can_back_coupon_price');
                }
            }
            // 完成售后单
            make(Aftersale::class)->where(['af_id' => $af_arr['af_id']])->update($af_data);
            // 订单退款
            $this->pay->refund($order_details['pay_order_sn'], $refund_price);

            $order_data = [
                'curr_af_id' => $af_instance->af_id,
                'refund_price' => Db::raw("refund_price+" . $refund_price)
            ];
            // 退款后判断订单是否全退，全退后关闭订单
            if ($order_details['order_style'] == FlyOrderService::STYLE_SEAT || $this->aftersale->getSuccessBackNum($af_arr['order_id']) == $order_details['product_num']) {
                $order_data['order_status'] = FlyOrderService::STATUS_FINISHED;// 全退完成订单
                $order_data['close_time'] = time();
            }
            $count = make(FlyOrder::class)
                ->where('order_id', '=', $af_arr['order_id'])
                ->whereRaw("refund_price+" . $refund_price . "<=paid_price")
                ->update($order_data);
            if (!$count) {
                Db::rollBack();
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '订单金额不足扣款');
            }
            /** ----------保存信息----------- **/
        } catch (\Throwable $exception) {
            Db::rollBack();
            echo $exception->getMessage();
            throw new BusinessException(ErrorCode::NORMAL_ERROR, $exception->getMessage());
        }
        Db::commit();
        return true;
    }

    /**
     * 商家自行配送
     * @param int $order_id
     * @param int $shop_id
     * @return bool
     */
    public function localSelfSend(int $order_id, int $shop_id): bool
    {
        return $this->sendDelivery->sendDelivery($order_id, $shop_id, ShopDeliveryConfigService::TYPE_LOCAL, ShopDeliveryConfigService::LOCAL_SEND_OWN);
    }

}